package com.kxmall.common.helper;

import cn.dev33.satoken.stp.StpUtil;
import com.kxmall.common.enums.DeviceType;
import com.kxmall.common.enums.UserType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Token隔离助手
 * 简单实现用户和骑手Token隔离，不修改token-prefix
 *
 * @author kxmall
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TokenIsolationHelper {

    // Token名称映射
    private static final String APP_TOKEN_NAME = "Authorization";
    private static final String RIDER_TOKEN_NAME = "Rider-Authorization";
    private static final String ADMIN_TOKEN_NAME = "Admin-Authorization";

    /**
     * 根据用户类型和设备类型获取Token名称
     */
    public static String getTokenName(UserType userType, DeviceType deviceType) {
        if (UserType.APP_USER.equals(userType) && DeviceType.APP.equals(deviceType)) {
            return APP_TOKEN_NAME;
        } else if (UserType.RIDER_USER.equals(userType) && DeviceType.RIDER.equals(deviceType)) {
            return RIDER_TOKEN_NAME;
        } else if (UserType.SYS_USER.equals(userType)) {
            return ADMIN_TOKEN_NAME;
        }
        return APP_TOKEN_NAME; // 默认
    }

    /**
     * 验证当前Token名称是否匹配期望的用户类型
     */
    public static boolean validateTokenName(UserType expectedUserType, DeviceType expectedDeviceType) {
        try {
            String expectedTokenName = getTokenName(expectedUserType, expectedDeviceType);
            String currentTokenName = StpUtil.getTokenName();
            
            boolean isValid = expectedTokenName.equals(currentTokenName);
            
            if (!isValid) {
                log.warn("🚨 Token名称验证失败 - 期望: {}, 实际: {}, 用户类型: {}, 设备类型: {}", 
                    expectedTokenName, currentTokenName, expectedUserType.getUserType(), expectedDeviceType.getDevice());
            } else {
                log.debug("✅ Token名称验证通过 - Token名称: {}, 用户类型: {}, 设备类型: {}", 
                    currentTokenName, expectedUserType.getUserType(), expectedDeviceType.getDevice());
            }
            
            return isValid;
        } catch (Exception e) {
            log.error("Token名称验证异常", e);
            return false;
        }
    }

    /**
     * 记录Token隔离信息
     */
    public static void logTokenIsolation(String operation, UserType userType, DeviceType deviceType, Long userId) {
        try {
            String tokenName = getTokenName(userType, deviceType);
            String currentTokenName = StpUtil.getTokenName();
            String tokenValue = StpUtil.getTokenValue();
            
            log.info("🔒 Token隔离 - 操作: {}, 用户类型: {}, 设备类型: {}, 用户ID: {}, 期望Token名称: {}, 实际Token名称: {}, Token前缀: {}", 
                operation, 
                userType.getUserType(), 
                deviceType.getDevice(), 
                userId,
                tokenName,
                currentTokenName,
                tokenValue != null ? tokenValue.substring(0, Math.min(10, tokenValue.length())) + "..." : "null");
                
        } catch (Exception e) {
            log.error("记录Token隔离信息异常", e);
        }
    }

    /**
     * 检查Token隔离状态
     */
    public static TokenIsolationStatus checkIsolationStatus() {
        try {
            String currentTokenName = StpUtil.getTokenName();
            String loginId = StpUtil.getLoginIdAsString();
            String device = StpUtil.getLoginDevice();
            
            // 根据LoginId判断用户类型
            UserType userType = null;
            if (loginId.startsWith("app_user:")) {
                userType = UserType.APP_USER;
            } else if (loginId.startsWith("rider_user:")) {
                userType = UserType.RIDER_USER;
            } else if (loginId.startsWith("sys_user:")) {
                userType = UserType.SYS_USER;
            }
            
            // 根据设备判断设备类型
            DeviceType deviceType = null;
            if ("app".equals(device)) {
                deviceType = DeviceType.APP;
            } else if ("rider".equals(device)) {
                deviceType = DeviceType.RIDER;
            } else if ("pc".equals(device)) {
                deviceType = DeviceType.PC;
            }
            
            if (userType != null && deviceType != null) {
                String expectedTokenName = getTokenName(userType, deviceType);
                boolean isIsolated = expectedTokenName.equals(currentTokenName);
                
                return new TokenIsolationStatus(isIsolated, userType, deviceType, currentTokenName, expectedTokenName);
            }
            
            return new TokenIsolationStatus(false, null, null, currentTokenName, "unknown");
            
        } catch (Exception e) {
            log.error("检查Token隔离状态异常", e);
            return new TokenIsolationStatus(false, null, null, "error", "error");
        }
    }

    /**
     * Token隔离状态类
     */
    public static class TokenIsolationStatus {
        private final boolean isolated;
        private final UserType userType;
        private final DeviceType deviceType;
        private final String currentTokenName;
        private final String expectedTokenName;

        public TokenIsolationStatus(boolean isolated, UserType userType, DeviceType deviceType, 
                                  String currentTokenName, String expectedTokenName) {
            this.isolated = isolated;
            this.userType = userType;
            this.deviceType = deviceType;
            this.currentTokenName = currentTokenName;
            this.expectedTokenName = expectedTokenName;
        }

        public boolean isIsolated() {
            return isolated;
        }

        public UserType getUserType() {
            return userType;
        }

        public DeviceType getDeviceType() {
            return deviceType;
        }

        public String getCurrentTokenName() {
            return currentTokenName;
        }

        public String getExpectedTokenName() {
            return expectedTokenName;
        }

        @Override
        public String toString() {
            return String.format("TokenIsolationStatus{isolated=%s, userType=%s, deviceType=%s, currentTokenName='%s', expectedTokenName='%s'}", 
                isolated, userType, deviceType, currentTokenName, expectedTokenName);
        }
    }
}
